using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CollabApp.Domain.Entities.Game;

/// <summary>
/// 游戏实体 - 存储单局游戏的基本信息和状态
/// 继承BaseEntity，支持软删除和时间戳功能
/// </summary>
[Table("games")]
public class Game : BaseEntity
{
    /// <summary>
    /// 关联房间ID - 外键，指向游戏所在的房间
    /// </summary>
    [Column("room_id")]
    public Guid RoomId { get; private set; }

    /// <summary>
    /// 游戏模式 - 经典模式、极速模式、道具狂欢、生存模式、团队模式
    /// </summary>
    [Column("game_mode")]
    public string GameMode { get; private set; } = "classic";

    /// <summary>
    /// 地图宽度 - 游戏区域的像素宽度（圆形地图的直径）
    /// </summary>
    [Column("map_width")]
    public int MapWidth { get; private set; } = 1000;

    /// <summary>
    /// 地图高度 - 游戏区域的像素高度（圆形地图的直径）
    /// </summary>
    [Column("map_height")]
    public int MapHeight { get; private set; } = 1000;

    /// <summary>
    /// 游戏时长 - 单局游戏的持续时间（秒）
    /// </summary>
    [Column("duration")]
    public int Duration { get; private set; } = 180;

    /// <summary>
    /// 地图类型 - 圆形、方形等地图形状
    /// </summary>
    [Column("map_shape")]
    public string MapShape { get; private set; } = "circle";

    /// <summary>
    /// 道具刷新间隔（秒）
    /// </summary>
    [Column("powerup_spawn_interval")]
    public int PowerUpSpawnInterval { get; private set; } = 25;

    /// <summary>
    /// 最大同时存在道具数量
    /// </summary>
    [Column("max_powerups")]
    public int MaxPowerUps { get; private set; } = 3;

    /// <summary>
    /// 特殊事件概率（百分比）
    /// </summary>
    [Column("special_event_chance")]
    public int SpecialEventChance { get; private set; } = 0;

    /// <summary>
    /// 是否启用动态平衡机制
    /// </summary>
    [Column("enable_dynamic_balance")]
    public bool EnableDynamicBalance { get; private set; } = true;

    /// <summary>
    /// 游戏状态 - 准备中、进行中、暂停、已结束
    /// </summary>
    [Column("status")]
    public GameStatus Status { get; private set; } = GameStatus.Preparing;

    /// <summary>
    /// 获胜者用户ID - 外键，指向获胜的用户，可为空
    /// </summary>
    [Column("winner_id")]
    public Guid? WinnerId { get; private set; }

    /// <summary>
    /// 游戏开始时间 - 实际游戏开始的时间戳
    /// </summary>
    [Column("started_at")]
    public DateTime? StartedAt { get; private set; }

    /// <summary>
    /// 游戏结束时间 - 游戏完成或终止的时间戳
    /// </summary>
    [Column("finished_at")]
    public DateTime? FinishedAt { get; private set; }

    /// <summary>
    /// 游戏数据快照 - JSON格式存储游戏结束时的状态数据
    /// </summary>
    [Column("game_data", TypeName = "json")]
    public string? GameData { get; private set; }

    // ============ 构造函数 ============

    /// <summary>
    /// 无参构造函数 - EF Core 必需
    /// </summary>
    private Game() { }

    /// <summary>
    /// 私有构造函数 - 仅限工厂方法调用
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="gameMode">游戏模式</param>
    /// <param name="mapWidth">地图宽度</param>
    /// <param name="mapHeight">地图高度</param>
    /// <param name="duration">游戏时长</param>
    /// <param name="mapShape">地图形状</param>
    private Game(Guid roomId, string gameMode = "classic", int mapWidth = 1000, 
                int mapHeight = 1000, int duration = 180, string mapShape = "circle")
    {
        RoomId = roomId;
        GameMode = gameMode;
        MapWidth = mapWidth;
        MapHeight = mapHeight;
        Duration = duration;
        MapShape = mapShape;
        Status = GameStatus.Preparing;
        PowerUpSpawnInterval = gameMode == "powerup_carnival" ? 8 : 25;
        MaxPowerUps = gameMode == "powerup_carnival" ? 9 : 3;
        SpecialEventChance = gameMode == "powerup_carnival" ? 10 : 0;
        EnableDynamicBalance = true;
    }

    // ============ 导航属性 ============
    
    /// <summary>
    /// 关联的房间实体 - 多对一关系
    /// </summary>
    [ForeignKey("RoomId")]
    public virtual Room.Room Room { get; set; } = null!;
    
    /// <summary>
    /// 获胜用户实体 - 多对一关系，可为空
    /// </summary>
    [ForeignKey("WinnerId")]
    public virtual Auth.User? Winner { get; set; }
    
    /// <summary>
    /// 游戏参与玩家列表 - 一对多关系
    /// </summary>
    public virtual ICollection<GamePlayer> Players { get; set; } = new List<GamePlayer>();
    
    /// <summary>
    /// 游戏操作记录列表 - 一对多关系，用于游戏回放
    /// </summary>
    public virtual ICollection<GameAction> Actions { get; set; } = new List<GameAction>();

    // ============ 工厂方法 ============

    /// <summary>
    /// 创建新游戏 - 工厂方法
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="gameMode">游戏模式</param>
    /// <param name="mapWidth">地图宽度</param>
    /// <param name="mapHeight">地图高度</param>
    /// <param name="duration">游戏时长</param>
    /// <param name="mapShape">地图形状</param>
    /// <returns>新游戏实例</returns>
    public static Game CreateGame(Guid roomId, string gameMode = "classic", 
                                  int mapWidth = 1000, int mapHeight = 1000, int duration = 180, string mapShape = "circle")
    {
        if (roomId == Guid.Empty)
            throw new ArgumentException("房间ID不能为空", nameof(roomId));
        if (string.IsNullOrWhiteSpace(gameMode))
            throw new ArgumentException("游戏模式不能为空", nameof(gameMode));
        if (mapWidth <= 0 || mapWidth > 5000)
            throw new ArgumentException("地图宽度必须在1-5000之间", nameof(mapWidth));
        if (mapHeight <= 0 || mapHeight > 5000)
            throw new ArgumentException("地图高度必须在1-5000之间", nameof(mapHeight));
        if (duration <= 0 || duration > 3600)
            throw new ArgumentException("游戏时长必须在1-3600秒之间", nameof(duration));

        return new Game(roomId, gameMode, mapWidth, mapHeight, duration, mapShape);
    }

    // ============ 业务方法 ============

    /// <summary>
    /// 开始游戏
    /// </summary>
    public void StartGame()
    {
        if (Status != GameStatus.Preparing)
            throw new InvalidOperationException("只能在准备状态下开始游戏");

        Status = GameStatus.Playing;
        StartedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// 结束游戏
    /// </summary>
    /// <param name="winnerId">获胜者ID</param>
    /// <param name="gameData">游戏数据快照</param>
    public void FinishGame(Guid? winnerId = null, string? gameData = null)
    {
        if (Status != GameStatus.Playing)
            throw new InvalidOperationException("只能在游戏进行状态下结束游戏");

        Status = GameStatus.Finished;
        FinishedAt = DateTime.UtcNow;
        WinnerId = winnerId;
        GameData = gameData;
    }

    /// <summary>
    /// 更新游戏数据
    /// </summary>
    /// <param name="gameData">游戏数据JSON</param>
    public void UpdateGameData(string gameData)
    {
        GameData = gameData;
    }

    /// <summary>
    /// 获取游戏总时长
    /// </summary>
    /// <returns>实际游戏时长（秒）</returns>
    public int? GetActualDuration()
    {
        if (StartedAt == null) return null;
        if (FinishedAt == null && Status == GameStatus.Playing)
            return (int)(DateTime.UtcNow - StartedAt.Value).TotalSeconds;
        if (FinishedAt != null)
            return (int)(FinishedAt.Value - StartedAt.Value).TotalSeconds;
        return null;
    }

    /// <summary>
    /// 检查游戏是否超时
    /// </summary>
    /// <returns>是否超时</returns>
    public bool IsTimedOut()
    {
        if (Status != GameStatus.Playing || StartedAt == null)
            return false;

        return (DateTime.UtcNow - StartedAt.Value).TotalSeconds > Duration;
    }

    /// <summary>
    /// 获取剩余时间（秒）
    /// </summary>
    /// <returns>剩余时间，如果游戏未开始返回null</returns>
    public int? GetRemainingTime()
    {
        if (Status != GameStatus.Playing || StartedAt == null)
            return null;

        var elapsed = (DateTime.UtcNow - StartedAt.Value).TotalSeconds;
        var remaining = Duration - elapsed;
        return remaining > 0 ? (int)remaining : 0;
    }

    /// <summary>
    /// 检查是否为大逃杀缩圈阶段（最后30秒）
    /// </summary>
    /// <returns>是否为缩圈阶段</returns>
    public bool IsInShrinkingPhase()
    {
        var remaining = GetRemainingTime();
        return remaining.HasValue && remaining.Value <= 30;
    }

    /// <summary>
    /// 根据玩家数量调整地图大小
    /// </summary>
    /// <param name="playerCount">玩家数量</param>
    public void AdjustMapSizeForPlayers(int playerCount)
    {
        if (playerCount <= 0) return;

        if (playerCount <= 4)
        {
            MapWidth = MapHeight = 800;
        }
        else if (playerCount <= 6)
        {
            MapWidth = MapHeight = 1000;
        }
        else
        {
            MapWidth = MapHeight = 1200;
        }
    }

    /// <summary>
    /// 检查是否允许提前结束（单一玩家占领70%地图）
    /// </summary>
    /// <param name="maxPlayerAreaPercentage">最大玩家占地百分比</param>
    /// <returns>是否允许提前结束</returns>
    public bool CanEndEarly(decimal maxPlayerAreaPercentage)
    {
        return Status == GameStatus.Playing && maxPlayerAreaPercentage >= 70m;
    }

    /// <summary>
    /// 获取适合当前模式的配置
    /// </summary>
    /// <returns>游戏配置信息</returns>
    public GameModeConfig GetGameModeConfig()
    {
        return GameMode.ToLower() switch
        {
            "speed" => new GameModeConfig 
            { 
                SpeedMultiplier = 1.5m,
                Description = "极速模式：移动速度+50%，90秒快速对战" 
            },
            "powerup_carnival" => new GameModeConfig 
            { 
                PowerUpSpawnRate = 3, 
                PowerUpEffectMultiplier = 1.5m,
                Description = "道具狂欢：道具刷新频率×3，效果时间×1.5" 
            },
            "survival" => new GameModeConfig 
            { 
                MaxLives = 1,
                Description = "生存模式：只有一条命，死亡即出局" 
            },
            "team" => new GameModeConfig 
            { 
                AllowTeamTerritory = true,
                Description = "团队模式：队友领地可以连通" 
            },
            _ => new GameModeConfig 
            { 
                Description = "经典模式：标准规则，适合所有玩家" 
            }
        };
    }
}

/// <summary>
/// 游戏模式配置
/// </summary>
public class GameModeConfig
{
    public decimal SpeedMultiplier { get; set; } = 1.0m;
    public int PowerUpSpawnRate { get; set; } = 1;
    public decimal PowerUpEffectMultiplier { get; set; } = 1.0m;
    public int MaxLives { get; set; } = int.MaxValue;
    public bool AllowTeamTerritory { get; set; } = false;
    public string Description { get; set; } = string.Empty;
}

/// <summary>
/// 游戏状态枚举
/// </summary>
public enum GameStatus
{
    /// <summary>
    /// 准备中 - 游戏已创建但尚未开始
    /// </summary>
    Preparing,
    
    /// <summary>
    /// 进行中 - 游戏正在进行
    /// </summary>
    Playing,
    
    /// <summary>
    /// 已结束 - 游戏已完成
    /// </summary>
    Finished
}
